package ihm.views.character_creator;

import ihm.actions.character_creator.CharacterNameAction;
import ihm.actions.character_creator.ClasseSelectedAction;
import ihm.actions.character_creator.CreateCharacterAction;
import ihm.actions.character_creator.FactionSelectedAction;
import ihm.actions.character_creator.LevelSelectedAction;
import ihm.controllers.ATKcontroller;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;
import java.awt.Toolkit;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JTextField;

import systems.languages.MultiLanguages;
import systems.rpgBuilder.Classe;
import systems.rpgBuilder.Faction;
import systems.rpgBuilder.RpgBuilder;

public class CharacterCreator extends JDialog
{
  private static final long serialVersionUID = 1L;
  /** Objects uses for the frame **/
  private LayoutManager     frameLayout;
  private GridBagConstraints  gbc;
  private ATKcontroller controller;
  /** **/
  private JLabel titleLabel;
  private JButton validateButton;
  //Name
  private JLabel typeNameLabel;
  private JTextField characterNameTextField;
  //Level
  private JLabel selectLevelLabel;
  private JComboBox levelComboBox = new JComboBox();
  //Faction
  private JLabel selectFactionLabel;
  private JComboBox factionComboBox = new JComboBox();
  private JLabel factionIcon;
  //Classe
  private JLabel selectClasseLabel;
  private JComboBox classeComboBox = new JComboBox();
  private JLabel classeIcon;
  
  

  /**
   * 
   * @param controler
   * @param model
   */
  public CharacterCreator(ATKcontroller controller)
  {
    this.controller = controller;
    this.initFrame();
    this.buildMainFrame();
    this.display();
  }

  /**
   * This method initializes the frame :
   * <ul>
   *  <li>Title of the frame</li>
   *  <li>Size of the frame</li>
   *  <li>If the frame is resizable</li>
   * </ul>
   * and deals with the frame container and the layout manager.
   */
  private void initFrame()
  {
    setTitle(MultiLanguages.getProperties("dialog.Create.title"));
    setSize(405, 315);
    setResizable(true);

    //Instantiating the Layout Manager
    this.frameLayout  = new GridBagLayout();
    // and the Constraint for this layout
    this.gbc = new GridBagConstraints();
    //Set the new layout.
    getContentPane().setLayout(this.frameLayout);
    //Set the Dialog Modal
    this.setModal(true);
  }

  /**
   * Initialized the level combobox
   */
  private void initLevelComboBox()
  {
    int minLvl, maxLvl;
    minLvl = RpgBuilder.getMinLevel();
    maxLvl = RpgBuilder.getMaxLevel();

    for(int lvl = minLvl; lvl <= maxLvl; lvl++)
      this.levelComboBox.addItem(lvl);
  }

  /**
   * Initialized the faction combobox.
   * This combobox contains all the faction created by the RpgBuilder.
   */
  private void initFactionComboBox()
  {
    List<Faction> factionList = RpgBuilder.getFactionsList();
    for(Faction faction : factionList)
      this.factionComboBox.addItem(faction);
  }

  /**
   * Initialized the classe combobox according to the faction and the level 
   * selected 
   */
  private void initClasseComboBox(Faction factionSelected)
  {
    this.classeComboBox.removeAllItems();
    List<Classe> classes = factionSelected.authorizedClasse();
    //Now we can filter the authorized classe according to the level selected
    int lvl = (Integer) this.levelComboBox.getSelectedItem();
    
    for(Classe classe : classes)
      //if the character's level is between the min and the max level of the 
      // classe we wan "keep it", else we removed it
      if(classe.getMinLvl()<=lvl && lvl<= classe.getMaxLvl()) 
        this.classeComboBox.addItem(classe);
    
    classeComboBox.validate();
  }
  
  private void initButtons()
  {
    this.validateButton = new JButton(MultiLanguages.getProperties("dialog.Create.validate"));
    this.validateButton.addActionListener(new CreateCharacterAction(this));
    this.validateButton.setEnabled(false);
  }
  /**
   * Instanciate JLabel according to the language.
   */
  private void updateLabel()
  {
    this.titleLabel = new JLabel("<html><h2>"+
        MultiLanguages.getProperties("dialog.Create.label")+
    "</h2></html>");
    this.typeNameLabel = new JLabel(MultiLanguages.getProperties("dialog.Create.name"));
    this.selectLevelLabel = new JLabel(MultiLanguages.getProperties("dialog.Create.level"));
    this.selectFactionLabel = new JLabel(MultiLanguages.getProperties("dialog.Create.faction"));
    this.selectClasseLabel = new JLabel(MultiLanguages.getProperties("dialog.Create.classe"));
  }

  private void buildMainFrame()
  {
    updateLabel();
    buildTitle();
    buildName();
    buildLevel();
    buildFaction();
    buildClasse();
    buildButtons();
  }


  /**
   * Build the header of the frame.
   * Note : The header is the title which will be display on top of the 
   * container of the frame.
   */
  private void buildTitle()
  {
    int gridx = 0;
    int gridy = 0;
    //Position
    this.gbc.gridx = gridx;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.CENTER;
    this.gbc.fill = GridBagConstraints.HORIZONTAL;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = GridBagConstraints.REMAINDER;
    //Adding
    this.add(this.titleLabel, this.gbc);
  }

  /**
   * Builds and displays the Components relative to the Character's name.
   */
  private void buildName()
  {
    int gridx = 0;
    int gridy = 1;
    /** The label **/
    //Position
    this.gbc.gridx = gridx;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.LINE_START;
    this.gbc.fill = GridBagConstraints.NONE;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = GridBagConstraints.RELATIVE;
    //Adding
    this.add(this.typeNameLabel, this.gbc);

    /** The TextField */
    this.characterNameTextField = new JTextField(
        MultiLanguages.getProperties("model.defaultCharacter.name")
    );
    this.characterNameTextField.addFocusListener(new CharacterNameAction(this.characterNameTextField));
    //Position
    this.gbc.gridx = ++gridx;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.LINE_START;
    this.gbc.fill = GridBagConstraints.HORIZONTAL;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = GridBagConstraints.REMAINDER;
    //Adding
    this.add(this.characterNameTextField, this.gbc);
  }

  /**
   * Creates and displays the Components relative to the Character's level.
   */
  private void buildLevel()
  {
    int gridx = 0;
    int gridy = 2;
    /** The label **/
    //Position
    this.gbc.gridx = gridx;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.LINE_START;
    this.gbc.fill = GridBagConstraints.NONE;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = 1;
    //Adding
    this.add(this.selectLevelLabel, this.gbc);

    /** The Combobox */
    this.initLevelComboBox();
    //this.levelComboBox.setSelectedIndex(0);
    this.levelComboBox.addItemListener(new LevelSelectedAction(this));
    //Position
    this.gbc.gridx = 1;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.LINE_END;
    this.gbc.fill = GridBagConstraints.NONE;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = 1;
    //Adding
    this.add(this.levelComboBox, this.gbc);

  }

  private void buildFaction()
  {
    int gridx = 0;
    int gridy = 3;
    /** The label **/
    this.selectFactionLabel.setEnabled(false);
    //Position
    this.gbc.gridx = gridx;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.LINE_START;
    this.gbc.fill = GridBagConstraints.NONE;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = 1;
    //Adding
    this.add(this.selectFactionLabel, this.gbc);

    /** The Combobox **/
    this.initFactionComboBox();
    this.factionComboBox.addItemListener(new FactionSelectedAction(this));
    this.factionComboBox.setEnabled(false);
    //Position
    this.gbc.gridx = ++gridx;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.LINE_END;
    this.gbc.fill = GridBagConstraints.NONE;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = GridBagConstraints.RELATIVE;
    //Adding
    this.add(this.factionComboBox, this.gbc);

    /** The Icon of the faction **/
    this.factionIcon = new JLabel(new ImageIcon(RpgBuilder.getFactionsList().get(0).getPicturePath()));
    this.factionIcon.setEnabled(false);
    //Position
    this.gbc.gridx = ++gridx;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.CENTER;
    this.gbc.fill = GridBagConstraints.NONE;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = GridBagConstraints.REMAINDER;
    //Adding
    this.add(this.factionIcon, this.gbc);
  }

  private void buildClasse()
  {
    int gridx = 0;
    int gridy = 4;
    this.selectClasseLabel.setEnabled(false);
    /** The label **/
    //Position
    this.gbc.gridx = gridx;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.LINE_START;
    this.gbc.fill = GridBagConstraints.NONE;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = 1;
    //Adding
    this.add(this.selectClasseLabel, this.gbc);

    /** The Combobox */
    this.initClasseComboBox(RpgBuilder.getFactionsList().get(0));
    this.classeComboBox.addItemListener(new ClasseSelectedAction(this));
    this.classeComboBox.setEnabled(false);
    //Position
    this.gbc.gridx = ++gridx;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.LINE_END;
    this.gbc.fill = GridBagConstraints.NONE;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = GridBagConstraints.RELATIVE;
    //Adding
    this.add(this.classeComboBox, this.gbc);

    /** The Icon of the classe **/
    this.classeIcon = new JLabel();
    this.classeIcon.setEnabled(false);
    //Position
    this.gbc.gridx = ++gridx;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.CENTER;
    this.gbc.fill = GridBagConstraints.NONE;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = GridBagConstraints.REMAINDER;
    //Adding
    this.add(this.classeIcon, this.gbc);
  }

  private void buildButtons()
  {
    this.initButtons();
    int gridx = 0;
    int gridy = 5;
    //Position
    this.gbc.gridx = gridx;
    this.gbc.gridy = gridy;
    this.gbc.anchor = GridBagConstraints.CENTER;
    this.gbc.fill = GridBagConstraints.NONE;
    //Dimension
    this.gbc.gridheight = 1;
    this.gbc.gridwidth = GridBagConstraints.RELATIVE;
    //Adding
    this.add(this.validateButton, this.gbc);
    /** The Validate Button */
  }
  
  public void updateClasses()
  {
    Faction selectedFaction = (Faction) this.factionComboBox.getSelectedItem();
    this.initClasseComboBox(selectedFaction);
    this.classeComboBox.setSelectedIndex(0);    
  }
 
  /**
   * @return the characterNameTextField
   */
  public JTextField getCharacterNameTextField() {
    return characterNameTextField;
  }

  /**
   * @return the levelComboBox
   */
  public JComboBox getLevelComboBox() {
    return levelComboBox;
  }

  /**
   * @return the factionComboBox
   */
  public JComboBox getFactionComboBox() {
    return factionComboBox;
  }

  /**
   * @return the classeComboBox
   */
  public JComboBox getClasseComboBox() {
    return classeComboBox;
  }

  /**
   * @return
   */
  public JLabel getFactionIconLabel()
  {
    return factionIcon;
  }


  /**
   * @return the validateButton
   */
  public JButton getValidateButton() {
    return validateButton;
  }

  /**
   * @return the selectLevelLabel
   */
  public JLabel getSelectLevelLabel() {
    return selectLevelLabel;
  }

  /**
   * @return the selectFactionLabel
   */
  public JLabel getSelectFactionLabel() {
    return selectFactionLabel;
  }

  /**
   * @return the selectClasseLabel
   */
  public JLabel getSelectClasseLabel() {
    return selectClasseLabel;
  }

  public ATKcontroller getController() {
    return this.controller;
  }
  public void display() {
    //On positionne la frame sur l'ecran avant de l'afficher
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    int height  = screenSize.height;
    int width   = screenSize.width;
    int x = (width - this.getWidth())/2;
    int y = (height - this.getHeight())/3; 
    this.setBounds(x, y, this.getWidth(), this.getHeight());
    this.setVisible(true);
  }

  public static void main(String[] args)
  {
    CharacterCreator cc = new CharacterCreator(null);
    cc.display();
  }

  public JLabel getClasseIconLabel() {
    return this.classeIcon;
  }
  
  public Classe getCharacterClasse()
  {
    return (Classe) this.classeComboBox.getSelectedItem();
  }
  
  public int getCharacterLevel()
  {
    return (Integer) this.levelComboBox.getSelectedItem();
  }
  
  
  public Faction getCharacterFaction()
  {
    return (Faction) this.factionComboBox.getSelectedItem();
  }
  
  /**
   * Returns the Character's name typed.
   * @return The character's name.
   */
  public String getCharacterName()
  {
    return this.characterNameTextField.getText();
  }
}